#include "GameSoundMgr.h"
#include "cocos2d.h"

#include "cocos-ext.h"
#include "SimpleAudioEngine.h"
USING_NS_CC;

#define ERRCHECK( result) \
if (result != FMOD_OK)	\
	{	\
	CCLOG("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));	\
	break;	\
}

GameSoundMgr::GameSoundMgr() : m_pSystem(NULL)
{
	init();
}

GameSoundMgr::~GameSoundMgr()
{
	CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(GameSoundMgr::update), this);
	for (FMOD::Sound* s : lt)
	{
		s->release();
	}

	do 
	{
		FMOD_RESULT  result = m_pSystem->close();
		ERRCHECK(result);

		result = m_pSystem->release();
		ERRCHECK(result);
	} while (0);
}

bool GameSoundMgr::init()
{
	bool bRet = false;
	do 
	{
		FMOD_RESULT  result = FMOD::System_Create(&m_pSystem);
		ERRCHECK(result);

		unsigned int      version;
		result = m_pSystem->getVersion(&version);
		ERRCHECK(result);
		if (version < FMOD_VERSION)
		{
			CCLOG("Error!  You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION);
			break;
		}

		result = m_pSystem->init(32, FMOD_INIT_NORMAL, 0);
		ERRCHECK(result);

		CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(GameSoundMgr::update), this, 0.01, false);
	} while (0);

	return bRet;
}
FMOD_RESULT F_CALLBACK channelCallBack(FMOD_CHANNEL *channel, FMOD_CHANNEL_CALLBACKTYPE type, void *commanddata1, void *commanddata2)
{
	if (type == FMOD_CHANNEL_CALLBACKTYPE_END)
	{

		FMOD::Sound* sound;
		((FMOD::Channel*)channel)->getCurrentSound(&sound);
		if (sound)
		{
			GameSoundMgr::getInstance()->removeSound(sound);			
		}
	}

	return FMOD_OK;
}
void GameSoundMgr::play(const char* pStrFilePath, bool bLoop)
{
	do 
	{
		FMOD::Sound* sound1 = nullptr;
		for (FMOD::Sound* s : lt)
		{
			void* ud;
			s->getUserData(&ud);
			if (strcmp(pStrFilePath, (const char*)ud) == 0)
			{
				sound1 = s;
				break;
			}
		}

		if (sound1 == nullptr)
		{
			std::string str = CCFileUtils::sharedFileUtils()->fullPathForFilename(pStrFilePath);
			FMOD_RESULT result = m_pSystem->createSound(str.c_str(), FMOD_HARDWARE, 0, &sound1);
			ERRCHECK(result);

			/* drumloop.wav has embedded loop points which automatically makes looping turn on, */
			result = sound1->setMode(bLoop ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF);
			/* so turn it off here.  We could have also just put FMOD_LOOP_OFF in the above CreateSound call. */
			ERRCHECK(result);

			lt.push_back(sound1);
			sound1->setUserData((void*)pStrFilePath);
		}
	
		FMOD_RESULT result = m_pSystem->playSound(FMOD_CHANNEL_FREE, sound1, false, 0);
		ERRCHECK(result);
	} while (0);
}

void GameSoundMgr::update(float dt)
{
	m_pSystem->update();
}

GameSoundMgr* GameSoundMgr::getInstance()
{
	static GameSoundMgr mgr;
	return &mgr;
}

void GameSoundMgr::playEffect(const char* pStrFilePath, bool bLoop /*= false*/)
{
	return play(pStrFilePath, bLoop);
}

void GameSoundMgr::removeSound(FMOD::Sound* sound)
{
	lt.push_back(sound);
}

void GameSoundMgr::playBackgroundMusic(const char* pStrFilePath, bool bLoop /*= false*/)
{
	if (m_bgMusic != pStrFilePath)
	{
		play(pStrFilePath, bLoop);
		m_bgMusic = pStrFilePath;
	}
}

